package com.itcast.proxy;

import com.itcast.service.AccountService;
import com.itcast.service.impl.AccountServiceImpl;
import com.itcast.service.impl.ServiceImpl;
import org.junit.Test;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class ProxyDemo {

    @Test
    public void test1() {
        //创建目标对象
        final AccountServiceImpl accountService = new AccountServiceImpl();

        //创建代理对象
        /*
         * JDK动态代理:基于接口，代理对象和目标对象拥有共同接口
         *  涉及的类：Proxy
         *  创建代理对象的方法：newProxyInstance()
         *      方法下的参数：
         *          第一个参数：代理的目标对象的类加载器（固定写法）
         *          第二个参数：代理的目标对象可能拥有的接口（固定写法）
         *          第三个参数：代理的具体实现（程序员自己去实现）
         */

        AccountService proxyInstance = (AccountService) Proxy.newProxyInstance(accountService.getClass().getClassLoader(), accountService.getClass().getInterfaces(), new InvocationHandler() {
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                Object obj;
                System.out.println("动态代理的方法");
                if (args != null && args.length > 0) {
                    obj = method.invoke(proxy, args[0]);
                } else {
                    obj = method.invoke(proxy);
                }
                return obj;
            }
        });

//        proxyInstance.find();
        proxyInstance.update(18);
    }


    @Test
    public void test2() {
        //1.创建目标对象
        final ServiceImpl accountService = new ServiceImpl();
        //2.创建代理对象
        /*
         * Cglib动态代理:基于父类
         *  涉及的类：Enhancer
         *  创建代理对象的方法：create()
         *      方法下的参数：
         *          第一个参数：代理的目标对象的字节码类型（固定写法）
         *          第二个参数：执行代理处理CallBack,使用其子接口MethodInterceptor（拦截执行的方法对象）
         */
        ServiceImpl  o = (ServiceImpl)Enhancer.create(accountService.getClass(), new MethodInterceptor() {
            /**
             * @param o
             * @param method
             * @param objects
             * @param methodProxy
             * @return java.lang.Object
             * @author JANME
             * @date 2020-08-28 20:45
             */
            public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
                System.out.println("开启事务......");
                return method.invoke(accountService, objects);
            }
        });

        //调用方法
        o.insert(18);
    }
}
